
#include "Box.hpp"
#include "Plane.hpp"

namespace Geometry {

Plane::Plane(glm::vec3 a, glm::vec3 b, glm::vec3 c) : _a(a), _b(b), _c(c) {}

Plane::Plane() : _a(0.0f), _b(1.0f, 0.0f, 0.0f), _c(0.0f, 0.0f, 1.0f) {}

Model::MeshRef Plane::CreateMesh(bool generateNormalTexCoords) {
  // TODO: Create a plane model area(1, 1)
  glm::vec3 planeNor = Normal();
  glm::vec3 planeX = glm::normalize(_b - _a);
  glm::vec3 planeY = glm::normalize(glm::cross(planeNor, planeX));
  // First Point
  std::vector<float> data;
  std::vector<Model::VertexAttribFormat> formats;
  glm::vec3 points[] = {_a + planeX + planeY, _a + (-planeX) + planeY,
                        _a + (-planeX) + (-planeY), _a + planeX + (-planeY)};
  Model::MeshRef planeMesh;
  planeMesh = Model::MeshData::CreateMeshData();
  if (generateNormalTexCoords) {
    // Generate TexCoords
    glm::vec2 texCoords[] = {glm::vec2(1.0f), glm::vec2(0.f, 1.f), glm::vec2(0.f),
                             glm::vec2(1.f, 0.f)};
    glm::vec3 normal(0.0f, 1.0f, 0.0f);
    formats.push_back({Model::DataType::FLOAT32, Model::AttribType::TexCoords, 0});
    formats.push_back({Model::DataType::FLOAT32, Model::AttribType::Pos, 2});
    formats.push_back({Model::DataType::FLOAT32, Model::AttribType::Norm, 5});

    for (int i = 0; i < 4; i++) {
      for (int j = 0; j < 3; j++) {
        if (j < 2)
          data.push_back(texCoords[i][j]);
        data.push_back(points[i][j]);
        data.push_back(normal[j]);
      }
    }
    planeMesh->Assign(data, formats);
  } else {
    formats.push_back({Model::DataType::FLOAT32, Model::AttribType::Pos, 0});
    for (int i = 0; i < 4; i++) {
      for (int j = 0; j < 3; j++)
        data.push_back(points[i][j]);
    }
    planeMesh->Assign(data, formats);
  }
  return planeMesh;
}

void Plane::SetOrigin(glm::vec3 o) { _a = o; }

void Plane::SetOtherPoint(glm::vec3 v1, glm::vec3 v2) {
  _b = v1;
  _c = v2;
}

bool Plane::InPlane(glm::vec3 point) const {
  if (glm::dot((point - _a), Normal()) == 0)
    return true;
  return false;
}

glm::vec3 Plane::Normal() const { return glm::cross(_b - _a, _c - _a); }

/* ----------------------------------------------------------- */
/* ----------------------------Box---------------------------- */
/* ----------------------------------------------------------- */

Model::MeshRef Box::CreateMesh(bool generateNormalTexCoords) {
  // TODO: Create a box mesh
  return nullptr;
}

} // namespace Geometry
